﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string>
using namespace std;

//lambda表达式

//可调用对象包括
//函数指针
//仿函数
//lambda

/*
lambda表达式本质是一个匿名函数对象 可以定义在函数内部
lambda表达式的格式:[捕捉列表](参数列表)-> 返回值 {函数体}
*/

/*
参数列表不需要时可以省略 
返回值类型也可省略 
函数体内可以使用其参数和捕获到的变量
*/

//int main()
//{
//	auto add1 = [](int x, int y)->int {return x + y; };
//	cout << add1(1, 2) << endl;
//
//	// 1、捕捉为空也不能省略
//	// 2、参数为空可以省略
//	// 3、返回值可以省略，可以通过返回对象自动推导
//	// 4、函数体不能省略
//	auto func1 = []
//	{
//		cout << "hello world" << endl;
//		return 10;
//	};
//
//	int x = func1(); //lambda表达式本质是一个函数对象
//	cout << x << endl;
//
//	int a = 0, b = 1;
//	auto swap1 = [](int& x, int& y)
//	{
//		int tmp = x;
//		x = y;
//		y = tmp;
//	};
//	swap1(a, b);
//	cout << a << ":" << b << endl;
//
//	return 0; 
//}

#include <vector>

struct Goods
{
	string _name;  // 名字
	double _price; // 价格
	int _evaluate; // 评价
	// ...

	Goods(const char* str, double price, int evaluate)
		:_name(str)
		, _price(price)
		, _evaluate(evaluate)
	{
	}
};

//仿函数实现比较
struct ComparePriceLess
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price < gr._price;
	}
};

struct ComparePriceGreater
{
	bool operator()(const Goods& g1, const Goods& g2)
	{
		return g1._price > g2._price;
	}
};

void Print(vector<Goods>& v)
{
	for (auto it = v.begin(); it != v.end(); ++it)
	{
		cout << it->_name << " " << it->_price << endl;
	}
	cout << "-------------------------------------" << endl;
}
#include <algorithm>

//int main()
//{
//	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2, 3}, { "菠萝", 1.5, 4 } };
//	//利用仿函数实现比较
//	//sort(v.begin(), v.end(), ComparePriceLess());
//	//Print(v);
//	//sort(v.begin(), v.end(), ComparePriceGreater());
//	//Print(v);
//
//	//可以使用lambda函数实现
//	//按价格升序比较
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
//		return g1._price < g2._price;
//		});
//	Print(v);
//
//	//按价格降序比较
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)
//		{
//			return g1._price > g2._price;
//		});
//	Print(v);
//	return 0;
//}

//捕捉列表的使用

int x = 0;
// 捕捉列表必须为空，因为全局变量不用捕捉就可以用，没有可被捕捉的变量
auto func1 = []()
	{
		x++;
	};

//int main()
//{
//	// 只能用当前lambda局部域和捕捉的对象和全局对象
//	int a = 0, b = 1, c = 2, d = 3;
//
//	//值捕捉就直接写变量名 引用捕捉要加上& 引用捕捉的变量可以修改变量的值
//	auto func1 = [a, &b]
//	{
//		// 值捕捉的变量不能修改，引用捕捉的变量可以修改
//		//a++;
//		b++;
//		int ret = a + b;
//
//		return ret;
//	};
//
//	cout << func1() << endl;
//
//	// 隐式值捕捉
//	// 用了哪些变量就捕捉哪些变量
//	auto func2 = [=]
//	{
//		int ret = a + b + c;
//		return ret;
//	};
//	cout << func2() << endl;
//
//	// 隐式引用捕捉
//	// 用了哪些变量就捕捉哪些变量
//	auto func3 = [&]
//	{
//		a++;
//		c++;
//		d++;
//	};
//	func3();
//	cout << a << " " << b << " " << c << " " << d << endl;
//
//	// 混合捕捉1
//	//混合捕捉时 隐式捕捉必须写在最前面
//	auto func4 = [&, a, b]
//	{
//		//a++;
//		//b++;
//		c++;
//		d++;
//		return a + b + c + d;
//	};
//	func4();
//	cout << a << " " << b << " " << c << " " << d << endl;
//
//	// 局部的静态和全局变量不能捕捉，也不需要捕捉
//	static int m = 0;
//	auto func6 = []
//	{
//		int ret = x + m;
//		return ret;
//	};
//
//	// 传值捕捉本质是一种拷贝,并且被const修饰了
//// mutable相当于去掉const属性，可以修改了
//// 但是修改了不会影响外面被捕捉的值，因为是一种拷贝
//	auto func7 = [=]()mutable
//	{
//		a++;
//		b++;
//		c++;
//		d++;
//
//		return a + b + c + d;
//	};
//	cout << func7() << endl;
//	cout << a << " " << b << " " << c << " " << d << endl;
//
//	return 0;
//}


//lambda原理
//lambda底层是仿函数对象 当说我们写了⼀个lambda 以后，编译器会⽣成⼀个对应的仿函数的类。
/*
仿函数的类名是编译按⼀定规则⽣成的，保证不同的 lambda ⽣成的类名不同，lambda参数/返
回类型/函数体就是仿函数operator()的参数/返回类型/函数体， lambda 的捕捉列表本质是⽣成
的仿函数类的成员变量，也就是说捕捉列表的变量都是 lambda 类构造函数的实参，当然隐式捕
捉，编译器要看使⽤哪些就传那些对象。
*/

class Rate
{
public:
	Rate(double rate)
		: _rate(rate)
	{
	}

	double operator()(double money, int year)
	{
		return money * _rate * year;
	}

private:
	double _rate;
};

int main()
{
	double rate = 0.49;
	// lambda
	auto r2 = [rate](double money, int year) {
		return money * rate * year;
		};

	// 函数对象
	Rate r1(rate);
	r1(10000, 2);
	r2(10000, 2);

	auto func1 = [] {
		cout << "hello world" << endl;
		};
	func1();

	return 0;
}